import { expect } from '@jest/globals';
import { JsonReader } from '@ohos/hvigor/src/base/util/json-reader';
import fse from 'fs-extra';
import JSON5 from 'json5';

import { initExecuteCommand, runHvigorAsync, runHvigorFailAsync } from '../../../../common/common';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType,
} from '../../../../plugins/project-builder/models/constants';
import { ICaseRecord } from '../../../../plugins/report-builder/report-models';
import { TestCaseBuilder } from '../../../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../../../plugins/task-builder/test-case';
import { TestTaskOptionBuilder } from '../../../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API10,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
  modulesOption: [ModuleTemplateType.StaticLibrary],
};

const testFun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  const command = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHap',
  });
  const moduleModuleJsonPath = project.getModule('entry').moduleModuleJsonPath();
  const moduleJson = await JsonReader.getJsonObj(moduleModuleJsonPath, 'utf-8');
  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.READ_MESSAGES',
      reason: '$string:module_desc',
    },
  ];
  await fse.writeFile(moduleModuleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('name为user_grant类型权限，usedScene字段缺省 ', result);
  expect(result.stderr).toContain('Failed :entry:default@PreBuild');
  expect(result.stderr).toContain('The reason and usedScene attributes are mandatory for user_grant permissions.');
  expect(result.stderr).toContain(`at ${moduleModuleJsonPath}`);
  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.READ_MESSAGES',
      usedScene: {
        abilities: ['EntryAbility'],
        when: 'inuse',
      },
    },
  ];
  await fse.writeFile(moduleModuleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result1 = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('name为user_grant类型权限，reason字段缺省 ', result1);
  expect(result1.stderr).toContain('Failed :entry:default@PreBuild');
  expect(result1.stderr).toContain('The reason and usedScene attributes are mandatory for user_grant permissions.');
  expect(result1.stderr).toContain(`at ${moduleModuleJsonPath}`);
  await testFunAtBackfill(moduleModuleJsonPath, moduleJson, projectRootPath, command, record).then(async () => {
    await testFunAsBuildHar(project, taskConfig, record);
  });
};

const testFunAtBackfill = async (moduleModuleJsonPath: string, moduleJson: any, projectRootPath: string, command: string[], record: ICaseRecord) => {
  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.READ_MESSAGES1',
    },
  ];
  await fse.writeFile(moduleModuleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result3 = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('name为非SDK配置权限 非definePermissions配置权限', result3);
  expect(result3.stderr).toContain('Failed :entry:default@PreBuild');
  expect(result3.stderr).toContain(
    'The ohos.permission.READ_MESSAGES1 permission under requestPermissions must be a value that is predefined within ' +
      'the SDK or a custom one that you have included under definePermissions.',
  );
  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.USE_BLUETOOTH',
    },
  ];
  await fse.writeFile(moduleModuleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result2 = await runHvigorAsync(projectRootPath, command);
  record.addStep('name为非user_grant类型权限，usedScene，reason字段缺省 ', result2);
  expect(result2.stdout).toContain('Finished :entry:default@PreBuild');
  expect(result2.stdout).toContain('BUILD SUCCESSFUL');
};

const testFunAsBuildHar: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  const command = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHar',
  });
  const moduleJsonPath = project.getModule('staticLibrary').moduleModuleJsonPath();
  const moduleJson = await JsonReader.getJsonObj(moduleJsonPath, 'utf-8');
  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.READ_MESSAGES',
    },
  ];
  await fse.writeFile(moduleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result = await runHvigorFailAsync(projectRootPath, command);
  record.addStep('har模块编译， name为user_grant类型权限，reason字段缺省 ', result);
  expect(result.stderr).toContain('Failed :staticLibrary:default@PreBuild');
  expect(result.stderr).toContain('The reason attribute are mandatory for user_grant permissions.');

  moduleJson.module.requestPermissions = [
    {
      name: 'ohos.permission.READ_MESSAGES',
      reason: '$string:page_show',
    },
  ];
  await fse.writeFile(moduleJsonPath, JSON5.stringify(moduleJson, null, 2), 'utf-8');
  const result1 = await runHvigorAsync(projectRootPath, command);
  record.addStep('har模块编译， name为user_grant类型权限，配置reason字段 ', result1);
  expect(result1.stdout).toContain('Finished :staticLibrary:default@PreBuild');
  expect(result1.stdout).toContain('BUILD SUCCESSFUL');
};

TestCaseBuilder.builder()
  .caseName('validateModuleJSONReqPermissions')
  .description('校验module.json5下reqPermissions字段，如果name为user_grant类型权限，则reason, usedScene字段必填')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.L2).build())
  .testFun(testFun)
  .load();
